const crypto = require('crypto');
const { nanoid } = require('nanoid');

/**
 * 通用辅助工具函数
 */

/**
 * 生成唯一ID
 * @param {number} length - ID长度
 * @returns {string} 唯一ID
 */
function generateId(length = 21) {
  return nanoid(length);
}

/**
 * 生成租户ID
 * @returns {string} 租户ID
 */
function generateTenantId() {
  return `tenant_${nanoid(16)}`;
}

/**
 * 生成API密钥
 * @returns {string} API密钥
 */
function generateApiKey() {
  return `sk_${nanoid(32)}`;
}

/**
 * 生成随机令牌
 * @param {number} length - 令牌长度
 * @returns {string} 随机令牌
 */
function generateToken(length = 32) {
  return crypto.randomBytes(length).toString('hex');
}

/**
 * 生成邀请码
 * @returns {string} 邀请码
 */
function generateInviteCode() {
  return nanoid(8).toUpperCase();
}

/**
 * 哈希字符串
 * @param {string} str - 要哈希的字符串
 * @param {string} algorithm - 哈希算法
 * @returns {string} 哈希值
 */
function hashString(str, algorithm = 'sha256') {
  return crypto.createHash(algorithm).update(str).digest('hex');
}

/**
 * 创建HMAC签名
 * @param {string} data - 要签名的数据
 * @param {string} secret - 密钥
 * @param {string} algorithm - 算法
 * @returns {string} 签名
 */
function createHmacSignature(data, secret, algorithm = 'sha256') {
  return crypto.createHmac(algorithm, secret).update(data).digest('hex');
}

/**
 * 验证HMAC签名
 * @param {string} data - 原始数据
 * @param {string} signature - 签名
 * @param {string} secret - 密钥
 * @param {string} algorithm - 算法
 * @returns {boolean} 是否有效
 */
function verifyHmacSignature(data, signature, secret, algorithm = 'sha256') {
  const expectedSignature = createHmacSignature(data, secret, algorithm);
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature));
}

/**
 * 格式化响应数据
 * @param {boolean} success - 是否成功
 * @param {*} data - 响应数据
 * @param {string} message - 响应消息
 * @param {Object} meta - 元数据
 * @returns {Object} 格式化的响应
 */
function formatResponse(success, data = null, message = null, meta = null) {
  const response = { success };
  
  if (message) {
    response.message = message;
  }
  
  if (data !== null) {
    response.data = data;
  }
  
  if (meta) {
    response.meta = meta;
  }
  
  return response;
}

/**
 * 创建成功响应
 * @param {*} data - 响应数据
 * @param {string} message - 响应消息
 * @param {Object} meta - 元数据
 * @returns {Object} 成功响应
 */
function successResponse(data = null, message = 'Success', meta = null) {
  return formatResponse(true, data, message, meta);
}

/**
 * 创建错误响应
 * @param {string} message - 错误消息
 * @param {Object} error - 错误详情
 * @param {number} statusCode - 状态码
 * @returns {Object} 错误响应
 */
function errorResponse(message = 'Error', error = null, statusCode = 500) {
  const response = formatResponse(false, null, message);
  
  if (error) {
    response.error = {
      statusCode,
      ...error
    };
  }
  
  return response;
}

/**
 * 创建分页响应
 * @param {Array} items - 数据项
 * @param {number} total - 总数
 * @param {number} page - 当前页
 * @param {number} limit - 每页数量
 * @param {string} message - 响应消息
 * @returns {Object} 分页响应
 */
function paginatedResponse(items, total, page, limit, message = 'Success') {
  const totalPages = Math.ceil(total / limit);
  const hasNext = page < totalPages;
  const hasPrev = page > 1;
  
  return successResponse(items, message, {
    pagination: {
      total,
      page,
      limit,
      totalPages,
      hasNext,
      hasPrev,
      nextPage: hasNext ? page + 1 : null,
      prevPage: hasPrev ? page - 1 : null
    }
  });
}

/**
 * 延迟执行
 * @param {number} ms - 延迟毫秒数
 * @returns {Promise} Promise对象
 */
function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

/**
 * 重试执行函数
 * @param {Function} fn - 要执行的函数
 * @param {number} retries - 重试次数
 * @param {number} delayMs - 重试间隔
 * @returns {Promise} Promise对象
 */
async function retry(fn, retries = 3, delayMs = 1000) {
  let lastError;
  
  for (let i = 0; i <= retries; i++) {
    try {
      return await fn();
    } catch (error) {
      lastError = error;
      
      if (i < retries) {
        await delay(delayMs * Math.pow(2, i)); // 指数退避
      }
    }
  }
  
  throw lastError;
}

/**
 * 深度克隆对象
 * @param {*} obj - 要克隆的对象
 * @returns {*} 克隆后的对象
 */
function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }
  
  if (obj instanceof Date) {
    return new Date(obj.getTime());
  }
  
  if (obj instanceof Array) {
    return obj.map(item => deepClone(item));
  }
  
  if (typeof obj === 'object') {
    const cloned = {};
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        cloned[key] = deepClone(obj[key]);
      }
    }
    return cloned;
  }
  
  return obj;
}

/**
 * 合并对象
 * @param {Object} target - 目标对象
 * @param {...Object} sources - 源对象
 * @returns {Object} 合并后的对象
 */
function mergeObjects(target, ...sources) {
  if (!sources.length) return target;
  const source = sources.shift();
  
  if (isObject(target) && isObject(source)) {
    for (const key in source) {
      if (isObject(source[key])) {
        if (!target[key]) Object.assign(target, { [key]: {} });
        mergeObjects(target[key], source[key]);
      } else {
        Object.assign(target, { [key]: source[key] });
      }
    }
  }
  
  return mergeObjects(target, ...sources);
}

/**
 * 检查是否为对象
 * @param {*} item - 要检查的项
 * @returns {boolean} 是否为对象
 */
function isObject(item) {
  return item && typeof item === 'object' && !Array.isArray(item);
}

/**
 * 获取嵌套对象属性
 * @param {Object} obj - 对象
 * @param {string} path - 属性路径 (如 'user.profile.name')
 * @param {*} defaultValue - 默认值
 * @returns {*} 属性值
 */
function getNestedProperty(obj, path, defaultValue = undefined) {
  const keys = path.split('.');
  let result = obj;
  
  for (const key of keys) {
    if (result === null || result === undefined || typeof result !== 'object') {
      return defaultValue;
    }
    result = result[key];
  }
  
  return result !== undefined ? result : defaultValue;
}

/**
 * 设置嵌套对象属性
 * @param {Object} obj - 对象
 * @param {string} path - 属性路径
 * @param {*} value - 属性值
 * @returns {Object} 修改后的对象
 */
function setNestedProperty(obj, path, value) {
  const keys = path.split('.');
  const lastKey = keys.pop();
  let current = obj;
  
  for (const key of keys) {
    if (!(key in current) || typeof current[key] !== 'object') {
      current[key] = {};
    }
    current = current[key];
  }
  
  current[lastKey] = value;
  return obj;
}

/**
 * 移除对象中的空值
 * @param {Object} obj - 对象
 * @returns {Object} 清理后的对象
 */
function removeEmptyValues(obj) {
  const cleaned = {};
  
  for (const [key, value] of Object.entries(obj)) {
    if (value !== null && value !== undefined && value !== '') {
      if (typeof value === 'object' && !Array.isArray(value)) {
        const nestedCleaned = removeEmptyValues(value);
        if (Object.keys(nestedCleaned).length > 0) {
          cleaned[key] = nestedCleaned;
        }
      } else {
        cleaned[key] = value;
      }
    }
  }
  
  return cleaned;
}

/**
 * 格式化文件大小
 * @param {number} bytes - 字节数
 * @param {number} decimals - 小数位数
 * @returns {string} 格式化的文件大小
 */
function formatFileSize(bytes, decimals = 2) {
  if (bytes === 0) return '0 Bytes';
  
  const k = 1024;
  const dm = decimals < 0 ? 0 : decimals;
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
  
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  
  return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}

/**
 * 生成随机颜色
 * @returns {string} 十六进制颜色值
 */
function generateRandomColor() {
  return '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0');
}

/**
 * 截断文本
 * @param {string} text - 文本
 * @param {number} length - 最大长度
 * @param {string} suffix - 后缀
 * @returns {string} 截断后的文本
 */
function truncateText(text, length = 100, suffix = '...') {
  if (!text || text.length <= length) {
    return text;
  }
  
  return text.substring(0, length - suffix.length) + suffix;
}

module.exports = {
  generateId,
  generateTenantId,
  generateApiKey,
  generateToken,
  generateInviteCode,
  hashString,
  createHmacSignature,
  verifyHmacSignature,
  formatResponse,
  successResponse,
  errorResponse,
  paginatedResponse,
  delay,
  retry,
  deepClone,
  mergeObjects,
  isObject,
  getNestedProperty,
  setNestedProperty,
  removeEmptyValues,
  formatFileSize,
  generateRandomColor,
  truncateText
};